Skip to content

Add phx.gen.release task for release/docker based deployments - #4609

Merged
chrismccord merged 20 commits into
masterfrom
cm-gen-docker
Dec 7, 2021
Merged

Add phx.gen.release task for release/docker based deployments#4609
chrismccord merged 20 commits into
masterfrom
cm-gen-docker

Conversation

@chrismccord

@chrismccord chrismccord commented Nov 23, 2021

Copy link
Copy Markdown
Member

I'm not super firm on env names, so would love feedback. The migrate and server shims are necessary for deployments where it's difficult for infrastructure to know what the OTP app name is. If we are happy with this direction, we can add bat scripts for windows to match migrate/server.

@chrismccord

Copy link
Copy Markdown
Member Author

The bin/server shim also aids folks who forget to set server: true in their config. This has been very frequent stumbling block over the years, so by generating runtime config that looks for the server env, we can also smooth over this particular stumbling block.

Comment thread priv/templates/phx.gen.docker/Dockerfile.eex Outdated
Co-authored-by: Michael Crumm <mike@crumm.net>

@Gazler Gazler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, covers most of the common cases. Big +1 for the server: true change.

Comment thread installer/lib/phx_new/generator.ex Outdated
For example: ecto://USER:PASS@HOST/DATABASE
\"""

ipv6? = System.get_env("IPV6") == "true"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is IPV6 the correct environment variable here? Since this is specific to the db socket, wouldn't something like DATABASE_IPV6 be more appropriate?

Comment thread lib/mix/tasks/phx.gen.docker.ex Outdated
Your application is ready to be deployed in a release!

# To start your system
_build/dev/rel/live_beats/bin/live_beats start

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/live_beats/#{app}

Comment thread lib/mix/tasks/phx.gen.docker.ex Outdated
File.chmod!("rel/overlays/bin/migrate", 0o700)
File.chmod!("rel/overlays/bin/server", 0o700)

Mix.shell().info("""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this shell info explain something about building for Docker vs release information from mix?

Comment thread lib/mix/tasks/phx.gen.docker.ex Outdated
])

Mix.Phoenix.copy_from(paths(), "priv/templates/phx.gen.docker/rel", binding, [
{:eex, "env.bat.eex", "rel/env.bat.eex"},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way we could leverage these from the existing mix release.init task to keep any changes in sync with the Elixir version?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we need to generate them. Could we tell them to use mix release.init if necessary?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we call this mix phx.gen.release and support a --docker flag?

# - https://pkgs.org/ - resource for finding needed packages
# - Ex: hexpm/elixir:1.12.3-erlang-24.1.4-debian-bullseye-20210902-slim
#
ARG BUILDER_IMAGE="hexpm/elixir:1.12.3-erlang-24.1.4-debian-bullseye-20210902-slim"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we leverage:

Application.spec(:elixir, :vsn) and :erlang.system_info(:version) (not sure how to get the minor version here)

So that the build image matches the elixir version in use?

This might have a downside as we can't ensure the image exists vs using a hard-coded string.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. We can do -erlang-24.1-, which perhaps is the safest choice.

Comment on lines +47 to +51
# note: if your project uses a tool like https://purgecss.com/,
# which customizes asset compilation based on what it finds in
# your Elixir templates, you will need to move the asset compilation
# step down so that `lib` is available.
COPY assets assets

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can asset compilation always be after lib? Won't it cover both cases with and without purgecss?

I don't know if there are any downsides of permanently moving it a step down, but this could make the generated dockerfile clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The downside is slower builds when you change something in lib. This would trigger and asset recompilation.

There's a way to do both with a multistage Dockerfile though, it's a good idea.

Comment thread installer/templates/phx_single/config/runtime.exs Outdated
Comment thread lib/mix/tasks/phx.gen.docker.ex Outdated
Comment thread installer/templates/phx_single/config/runtime.exs Outdated
server? = System.get_env("SERVER") == "true"

config :<%= @app_name %>, <%= @endpoint_module %>,
url: [host: host, port: 80],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I am happy with the hardcoded port here. I am wondering if instead we could support url as a string which we will parse. So we could do: url: System.get_env("PHX_URL"), and we set PHX_URL=example.com:80. The code would parse the string and discard all nil fields?

Comment thread lib/mix/tasks/phx.gen.docker.ex Outdated
@doc false
def run(_args) do
if Mix.Project.umbrella?() do
Mix.raise("mix phx.gen.docker is not supported in umbrella applications")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention they should generate it within their web app instead?

@chrismccord chrismccord changed the title Add phx.gen.docker task for docker release based deployments Add phx.gen.release task for release/docker based deployments Dec 3, 2021
@chrismccord

Copy link
Copy Markdown
Member Author

Updates:

  • The task has been renamed to phx.gen.release with an optional --docker flag for the Dockerfile.
  • Env vars included in config/runtime.exs for new apps are: ECTO_IPV6, PHX_HOST, and PHX_SERVER
  • Warnings are printed after the task is run if above env vars are not found in the file with instructions
  • Default :url port for production is set to 443, which is something we should have defaulted to a long time ago
  • The mix release.init files are no longer generated as they are not necessary and a user can opt-in to them in the future by running mix release.init

Comment thread installer/lib/phx_new/generator.ex Outdated
Comment thread installer/templates/phx_single/config/runtime.exs Outdated
Mix.shell().info(msg)
end
end
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is gorgeous.

Comment thread priv/templates/phx.gen.release/Dockerfile.eex Outdated
Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
Comment thread priv/templates/phx.gen.release/rel/migrate.sh.eex Outdated
@@ -0,0 +1,3 @@
#!/bin/sh
cd -P -- "$(dirname -- "$0")"
PHX_SERVER=true ./<%= otp_app %> start

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar here:

Suggested change
PHX_SERVER=true ./<%= otp_app %> start
exec PHX_SERVER=true ./<%= otp_app %> start

I don't know if exec should come before or after the env var.

Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
Comment on lines +165 to +166
IO.warn("unable to read OTP minor version at #{path}. Falling back to #{major}.0.0")
"#{major}.0.0"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IO.warn("unable to read OTP minor version at #{path}. Falling back to #{major}.0.0")
"#{major}.0.0"
IO.warn("unable to read OTP minor version at #{path}. Falling back to #{major}.0")
"#{major}.0"

Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
Comment on lines +160 to +162
with {:ok, content} <- File.read(path),
{:ok, %Version{} = vsn} <- Version.parse(String.trim_trailing(content)) do
"#{vsn.major}.#{vsn.minor}.#{vsn.patch}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTP versioning is... tricky. There is no 24.1.0, it is just 24.1. But i guess you could do this:

Suggested change
with {:ok, content} <- File.read(path),
{:ok, %Version{} = vsn} <- Version.parse(String.trim_trailing(content)) do
"#{vsn.major}.#{vsn.minor}.#{vsn.patch}"
with {:ok, content} <- File.read(path) do
String.trim(content)

Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
Comment thread lib/mix/tasks/phx.gen.release.ex Outdated
chrismccord and others added 8 commits December 7, 2021 10:27
@chrismccord
chrismccord merged commit 380a281 into master Dec 7, 2021
@chrismccord
chrismccord deleted the cm-gen-docker branch December 7, 2021 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants